home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / EXAMPLES / TRIPPY.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  10.1 KB  |  472 lines

  1.  
  2. /* 
  3.  * Texture feedback demo
  4.  * Simon Green 6/97
  5.  * si@sgi.com
  6.  *
  7.  * Compile:  
  8.  * cc -o feedback feedback.c -lglut -lGLU -lGL -lXmu -lXext -lX11 -lm
  9.  *
  10.  * Description:
  11.  * This is an old effect - it's kind of like pointing a video camera at a TV
  12.  * displaying the signal from itself.
  13.  * 
  14.  * It also demonstrates the OpenGL 1.1 glCopyTexImage2D function to copy
  15.  * texture data direct from the framebuffer. You'll need a machine with
  16.  * reasonably fast texture mapping for it to be fun.
  17.  *
  18.  * Usage:
  19.  * Start it up, hold down the left mouse button and move the mouse up and down
  20.  * and left and right slowly. Play with the menus. Enjoy!
  21.  *
  22.  * Left mouse button - zoom / rotate
  23.  * Right mouse button - translate (advanced users only)
  24.  *
  25.  * Bugs:
  26.  * Don't try resizing the window. Don't stare at it for too long.
  27.  */
  28.  
  29. #include <math.h> 
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <GL/glut.h>
  34.  
  35. #ifdef GL_VERSION_1_1
  36.  
  37. /* Some <math.h> files do not define M_PI... */
  38. #ifndef M_PI
  39. #define M_PI 3.14159265358979323846
  40. #endif
  41.  
  42. #define MAXSIZE 512             /* Set this to your maximum texture size (square)
  43. */
  44. #define TEXT_MESSAGE    "OpenGL"
  45.  
  46. float ang = 2.0;
  47. float scale = 1.05;
  48. float tx = 0.0, ty = 0.0;
  49.  
  50. int oldx, oldy;
  51. int lmb = 0;
  52. int mmb = 0;
  53. int autospin = 0;
  54. float atime = 0.0;
  55.  
  56. int smooth = 1;
  57. int seedmode = 0;
  58. float seedsize = 0.1;
  59.  
  60. int primtype = GL_LINES;
  61. float primsize = 1.0;
  62. int nprims = 10;
  63.  
  64. float r, g, b;
  65. float dr, dg, db;
  66. int randomcolours = 0;
  67.  
  68.  
  69. /* returns a random floating point number between 0.0 and 1.0 */
  70. float frand(void) {
  71.     return (float) (rand() / 32767.0);
  72. }
  73.  
  74. void init_colours(float speed)
  75. {
  76.     r = frand(); g = frand(); b = frand();
  77.     dr = frand() / speed; dg = frand() / speed; db = frand() / speed;    
  78. }
  79.  
  80. void bounce(float *n, float *dn)
  81. {
  82.     *n += *dn;
  83.     if (*n > 1.0) { *n = 1.0; *dn = -*dn; }
  84.     if (*n < 0.0) { *n = 0.0; *dn = -*dn; }
  85. }
  86.  
  87. /* generate pretty colours by bouncing rgb values up and down */
  88. void set_colour(void)
  89. {
  90.     if (randomcolours) {
  91.         glColor3f(frand(), frand(), frand());
  92.     } else {
  93.         bounce(&r, &dr);
  94.         bounce(&g, &dg);
  95.         bounce(&b, &db);
  96.         glColor3f(r, g, b);
  97.     }
  98. }
  99.  
  100.  
  101. /* seed pattern with some random primitives in centre of screen */
  102. void seed(void)
  103. {
  104.     int i;
  105.         
  106.     glBegin(primtype);
  107.     for(i=0; i<nprims; i++) {
  108.         set_colour();
  109.         glVertex2f((frand() - 0.5) * seedsize, (frand() - 0.5) * seedsize);
  110.     }
  111.     glEnd();
  112. }
  113.  
  114.  
  115. /* seed pattern with a circular pattern */
  116. void seed_circle(void)
  117. {   
  118.     int i;
  119.     double a;
  120.         
  121.     glBegin(primtype);
  122.         for(i=0; i<nprims; i++) {
  123.         a = ((double) i * 2 * M_PI) / nprims;
  124.         glColor4f(0.0, 0.0, 0.0, 1.0);
  125.         glVertex2d(0.0, 0.0);
  126.         set_colour();
  127.         glVertex2d(sin(a) * (seedsize / 2.0), cos(a) * (seedsize / 2.0));
  128.     }
  129.     glEnd();    
  130. }
  131.  
  132. /* bit of a silly one, this */
  133. void seed_teapot(void)
  134. {
  135.     glLoadIdentity();
  136.     glTranslatef((frand() - 0.5) * seedsize, (frand() - 0.5) * seedsize, 0.0);
  137.     glRotatef(frand() * 360.0, frand(), frand(), frand());
  138.  
  139.     set_colour();
  140.     glutWireTeapot(seedsize);
  141. }
  142.  
  143.  
  144. /* seed with text string */
  145. void seed_text(char *string)
  146. {
  147.     int i;
  148.     int width = 0;
  149.  
  150.     for (i = 0; i < (int) strlen(string); i++) {
  151.         width += glutStrokeWidth(GLUT_STROKE_ROMAN, string[i]);
  152.     }
  153.  
  154.     glLoadIdentity();
  155.     glScalef(seedsize / 100.0, seedsize / 100.0, seedsize / 100.0);
  156.     glTranslatef(-width / 2.0, -50.0, 0.0);
  157.  
  158.     for (i = 0; i < (int) strlen(string); i++) {
  159.         set_colour();
  160.         glutStrokeCharacter(GLUT_STROKE_ROMAN, string[i]);
  161.     }
  162. }
  163.  
  164.  
  165.  
  166. /* copy screen image to texture memory */
  167. void grab_screen(void)
  168. {
  169.     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, MAXSIZE, MAXSIZE,
  170. 0);
  171.  
  172.     if (smooth) {
  173.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  174.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  175.     } else {
  176.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  177.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  178.     }
  179.     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,  GL_DECAL);
  180.     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
  181. }
  182.  
  183.  
  184. void reset(void)
  185. {
  186.     ang = 0.0;
  187.     scale = 1.0;
  188.     tx = ty = 0.0;
  189.     autospin = 0;
  190.  
  191.     glClear(GL_COLOR_BUFFER_BIT);
  192.     grab_screen();
  193. }
  194.  
  195.  
  196. void redraw(void)
  197. {
  198.     glClear(GL_COLOR_BUFFER_BIT);           
  199.  
  200.     glMatrixMode(GL_MODELVIEW);
  201.     glLoadIdentity();
  202.     glTranslatef(tx, ty, 0.0);
  203.     glRotatef(ang, 0.0, 0.0, 1.0);
  204.     glScalef(scale, scale, scale);
  205.  
  206.     if (autospin) {
  207.         ang = 3.0 * cos(atime);
  208.         scale = 1.0 + ( sin(atime / 4.0) * 0.1) ;
  209.         atime += 0.01;
  210.     }
  211.  
  212.     /* draw feedback square */
  213.     glEnable(GL_TEXTURE_2D);
  214.     glBegin(GL_QUADS);
  215.         glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, -1.0);
  216.         glTexCoord2f(1.0, 0.0); glVertex2f(1.0, -1.0);
  217.         glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 1.0);
  218.         glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, 1.0);
  219.     glEnd();
  220.     glDisable(GL_TEXTURE_2D);
  221.     
  222.     /* draw square outline */
  223.     glColor3f(1.0, 1.0, 1.0);
  224.     glBegin(GL_LINE_LOOP);
  225.         glVertex2f(-1.0, -1.0);
  226.         glVertex2f(1.0, -1.0);
  227.         glVertex2f(1.0, 1.0);
  228.         glVertex2f(-1.0, 1.0);
  229.     glEnd();
  230.     
  231.     /* seed pattern */
  232.     glLoadIdentity();
  233.     switch(seedmode) {
  234.     case 0:
  235.         seed();
  236.         break;
  237.     case 1:
  238.         seed_circle();
  239.         break;
  240.     case 2:
  241.         seed_teapot();
  242.         break;
  243.     case 3:
  244.         seed_text(TEXT_MESSAGE);
  245.         break;
  246.     }
  247.  
  248.     /* grab screen as texture */
  249.     grab_screen();
  250.      
  251.     glutSwapBuffers();
  252. }
  253.  
  254.  
  255. void mouse(int button, int state, int x, int y)
  256. {
  257.     if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
  258.         lmb = 1;
  259.         oldx = x; oldy = y;
  260.     }
  261.     if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
  262.         lmb = 0;
  263.     }
  264.   
  265.     if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) {
  266.         mmb = 1;
  267.         oldx = x; oldy = y;
  268.     }
  269.     if (button == GLUT_MIDDLE_BUTTON && state == GLUT_UP) {
  270.         mmb = 0;
  271.     }
  272.  
  273. }
  274.  
  275. void motion(int x, int y)
  276. {
  277.     if (lmb) {
  278.         ang += ((oldx - x) / 4.0 );
  279.         scale += ((oldy - y) / 400.0);
  280.  
  281.         oldx = x; oldy = y;
  282.         glutPostRedisplay();
  283.     }
  284.     if (mmb) {
  285.         tx += ((float) (x - oldx)) / 500.0;
  286.         ty += ((float) (oldy - y)) / 500.0;
  287.  
  288.         oldx = x; oldy = y;
  289.         glutPostRedisplay();      
  290.     }
  291. }
  292.  
  293.  
  294. void main_menu(int i)
  295. {
  296.     switch(i) {
  297.     case 1:
  298.         autospin = !autospin;
  299.         atime = 0.0;
  300.         break;
  301.     case 2:
  302.         reset();
  303.         break;
  304.     case 3:
  305.         exit(0);
  306.     }
  307. }
  308.  
  309. void mode_menu(int i)
  310. {
  311.     smooth = i;
  312. }
  313.  
  314. void seed_menu(int i)
  315. {
  316.     seedmode = i;
  317. }
  318.  
  319. void prim_menu(int i)
  320. {
  321.     primtype = i;
  322. }
  323.  
  324. void size_menu(int i)
  325. {
  326.     seedsize = 1.0 / i;
  327. }
  328.  
  329. void psize_menu(int i)
  330. {
  331.     primsize = (float) i;
  332.  
  333.     glPointSize(primsize);
  334.     glLineWidth(primsize);
  335. }
  336.  
  337.  
  338. void no_menu(int i)
  339. {
  340.     nprims = i;
  341. }
  342.  
  343.  
  344. void colour_menu(int i)
  345. {
  346.     switch(i) {
  347.     case 0:
  348.         init_colours(500.0);
  349.         randomcolours = 0;
  350.         break;
  351.     case 1:
  352.         init_colours(100.0);
  353.         randomcolours = 0;
  354.         break;
  355.     case 2:
  356.         init_colours(10.0);
  357.         randomcolours = 0;
  358.         break;
  359.     case 3:
  360.         randomcolours = 1;
  361.         break;
  362.     }
  363. }
  364.  
  365. int mainmenu;
  366. int modemenu, seedmenu, primmenu, sizemenu, psizemenu, nomenu,
  367. colourmenu;
  368.  
  369. void create_menus(void)
  370. {
  371.     modemenu = glutCreateMenu(mode_menu);    
  372.     glutAddMenuEntry("Chunky", 0);
  373.     glutAddMenuEntry("Smooth", 1);
  374.  
  375.     seedmenu = glutCreateMenu(seed_menu);    
  376.     glutAddMenuEntry("Primitives", 0);
  377.     glutAddMenuEntry("Circle", 1);
  378.     glutAddMenuEntry("Teapot", 2);
  379.     glutAddMenuEntry("Text", 3);    
  380.  
  381.     colourmenu = glutCreateMenu(colour_menu);    
  382.     glutAddMenuEntry("Slow", 0);
  383.     glutAddMenuEntry("Medium", 1);
  384.     glutAddMenuEntry("Fast", 2);
  385.     glutAddMenuEntry("Random", 3);
  386.     
  387.     primmenu = glutCreateMenu(prim_menu);    
  388.     glutAddMenuEntry("Dots", GL_POINTS);
  389.     glutAddMenuEntry("Lines", GL_LINES);
  390.     glutAddMenuEntry("Triangles", GL_TRIANGLES);
  391.  
  392.     sizemenu = glutCreateMenu(size_menu);
  393.     glutAddMenuEntry("Tiny", 20);
  394.     glutAddMenuEntry("Small", 10);
  395.     glutAddMenuEntry("Medium", 5);
  396.     glutAddMenuEntry("Large", 2);
  397.  
  398.     nomenu = glutCreateMenu(no_menu);
  399.     glutAddMenuEntry("1", 1);
  400.     glutAddMenuEntry("2", 2);
  401.     glutAddMenuEntry("3", 3);
  402.     glutAddMenuEntry("5", 5);
  403.     glutAddMenuEntry("10", 10);
  404.     glutAddMenuEntry("20", 20);
  405.     glutAddMenuEntry("30", 30);
  406.     glutAddMenuEntry("50", 50);
  407.  
  408.     psizemenu = glutCreateMenu(psize_menu);
  409.     glutAddMenuEntry("1", 1);
  410.     glutAddMenuEntry("3", 3);
  411.     glutAddMenuEntry("5", 5);
  412.  
  413.     mainmenu = glutCreateMenu(main_menu);
  414.     glutAddSubMenu("Texture mode", modemenu);
  415.     glutAddSubMenu("Seed mode", seedmenu);
  416.     glutAddSubMenu("Seed size", sizemenu);
  417.     glutAddSubMenu("Colours", colourmenu);
  418.  
  419.     glutAddMenuEntry("-----------", -1);
  420.  
  421.     glutAddSubMenu("Primitive", primmenu);
  422.     glutAddSubMenu("Number", nomenu);
  423.     glutAddSubMenu("Size", psizemenu);
  424.  
  425.     glutAddMenuEntry("-----------", 0);
  426.     glutAddMenuEntry("Autospin", 1);
  427.     glutAddMenuEntry("Reset", 2);
  428.     glutAddMenuEntry("Quit", 3);
  429.     
  430.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  431. }
  432.  
  433.  
  434. int main(int argc, char **argv)
  435. {
  436.     glutInit(&argc, argv);
  437.     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
  438.     glutCreateWindow("feedback");
  439.     glutReshapeWindow(MAXSIZE, MAXSIZE);
  440.     glutDisplayFunc(redraw);
  441.     glutIdleFunc(redraw);
  442.     glutMouseFunc(mouse);
  443.     glutMotionFunc(motion);
  444.   
  445.     create_menus();
  446.     init_colours(100.0);
  447.   
  448.     glMatrixMode(GL_PROJECTION);
  449.     glLoadIdentity();
  450.     glOrtho(-1.0, 1.0, -1.0, 1.0, 0.0, 1.0);
  451.     glViewport(0, 0, MAXSIZE, MAXSIZE);
  452.  
  453.     glMatrixMode(GL_MODELVIEW);
  454.     glLoadIdentity();
  455.  
  456.     glutMainLoop();
  457.     return 0;             /* ANSI C requires main to return int. */
  458. }
  459.  
  460. #else
  461.  
  462. int
  463. main(int argc, char** argv)
  464. {
  465.     fprintf (stderr, "This program demonstrates a feature which is not in OpenGL Version 1.0.\n");
  466.     fprintf (stderr, "If your implementation of OpenGL Version 1.0 has the right extensions,\n");
  467.     fprintf (stderr, "you may be able to modify this program to make it run.\n");
  468.     return 0;
  469. }
  470.  
  471. #endif
  472.